#!/bin/bash
#  This program is free software; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation; either version 2 of the License, or
#  (at your option) any later version.
#  
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#  
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software
#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
#  MA 02110-1301, USA.
#  


# lock - disallow running two instances of the script
lockfile=/tmp/.rotate.sh.lock
if (set -C; >$lockfile); then
	trap 'rm -f $lockfile' 0 # execute when script finishes
else
	echo ANOTHER INSTANCE RUNNING
	#exit; # another instance running
fi 2>/dev/null

# config
FULL_PATH=/home/serwus/szperu/
# getopts config
SCAN_MAX_KIDS_NUM=1
SCAN_CONDITION=true
SCAN_MINUTES=$[6*3600]
SCAN_ACTIVE_MINUTES=20
PING_FILE_TO_WRITE_ACTIVE_HOSTS=/var/www/qsearch/active_hosts
QSEARCH_BINARY=$FULL_PATH/qsearch/qsearch
MYSQL_CMD="mysql -r -s -u serwus --password=serwus123 qsearch -e "
DOMAIN_APPEND=".pw.edu.pl"
DEBUG=false
QSEARCH_TABLE="qsearch6"
HOSTS_TABLE="hosts3"
LOOP_TIME=false
function_pnt=""

function usage() 
{
	echo "usage: $0 [-hnpsbd] [-a <num>] [-t <num>] [-m <string>]"
	echo "          [-P <string>] [-q <string>] [-H <string>] [-B <string>]"
	echo "          [-l <num>]"
	echo "-h help"
	echo "-n get_hosts"
	echo "-p ping hosts"
	echo "-s scan_hosts"
	echo "-b SCAN_CONDITION"
	echo "-a KIDSNUM"
	echo "-t minutes to scan"
	echo "-m MYSQL_CMD $MYSQL_CMD"
	echo "-P dommand append $DOMAIN_APPEND"
	echo "-d debug"
	echo "-q QSEARCH_TABLE $QSEARCH_TABLE"
	echo "-H HOSTS_TABLE $HOSTS_TABLE"
	echo "-B qsearch binary $QSEARCH_BINARY"
	echo "-r scan in parallel"
	echo "-l loop whole processs with loop_time seconds "
	exit 0;
}

while getopts "123hnpsa:bdt:m:P:q:H:B:r" arg; do
	case $arg in
	h)
		usage
	;;
	n|1)
#		function_pnt="get_hosts"
	;;
	p|2)
		function_pnt="ping_hosts"
	;;
	s|3)
		function_pnt="scan_hosts"
	;;
	a)
		test ! "${OPTARG}" -eq "${OPTARG}" ] 2>/dev/null && ( echo "${OPTARG} not a number."; exit -1 )
		SCAN_MAX_KIDS_NUM=${OPTARG}
	;;
	b)
		SCAN_CONDITION=false
	;;
	t)
		test ! "${OPTARG}" -eq "${OPTARG}" ] 2>/dev/null && ( echo "${OPTARG} not a number."; exit -1 )
		SCAN_MINUTES=${OPTARG}
	;;
	m)
		MYSQL_CMD=${OPTARG}
	;;
	P)
		DOMAIN_APPEND=${OPTARG}
	;;
	d)
		DEBUG=true
	;;
	q)
		QSEARCH_TABLE=${OPTARG}
	;;
	H)
		HOSTS_TABLE=${OPTARG}
	;;
	B)
		QSEARCH_BINARY=${OPTARG}
	;;
	r)
		PARALLEL=true
	;;
	l)
		test ! "${OPTARG}" -eq "${OPTARG}" ] 2>/dev/null && ( echo "${OPTARG} not a number."; exit -1 )
		LOOP_TIME=${OPTARG}
	;;
	esac
done
test -z "$function_pnt" && usage

function _get_hosta()
{
	local hostname
	local ip=$1
	host $ip >/dev/null && 
		(
			hostname=$(host $ip | awk '{print $5}' | sed 's/'$DOMAIN_APPEND'\.//')
			echo $ip $hostname exists!
			$MYSQL_CMD "insert into $HOSTS_TABLE values ('$ip', '$hostname', '1000-01-01 00:00:00', '1000-01-01 00:00:00')"
		)
	
}
function get_hosts()
{
	local kids=""
	
	trap "killall scan.sh" SIGINT
	
	# recreatuj tablice
	$MYSQL_CMD "create table if not exists $HOSTS_TABLE  (ip varchar(16), hostname varchar(30), scanned datetime, active datetime );"
	$MYSQL_CMD "truncate table $HOSTS_TABLE"
	
# hosty automatycznie skanowane
# to jest poprzedzone dokladna analiza sieci akademickiej, i oglasza sie co nastepuje
# hosty istnieją tylko w 10.x.x.x, gdzie x nalezy do 0 1 2 3 4 5 6 7 8 11 12 14 15 255
# 10.0.1.x - hosty od 2 do 12 jakies podstawowe
# 10.1.x.x - riviera
# 10.2.x.x - mikrus
# 10.3.x.x - ustronie
# 10.4 - akademik
# 10.5 - muszelka
# 10.6 - tulipan 
# 10.7 - babilon
# 10.8 - zaczek
# 10.11 - pineska
# 10.12 - bratniak
# 10.14 - servery - student to backbone, muszelka-to-akademikrtr.student.pw.edu.pl, nieskanujemu
# 10.15 - servery elki. nie skanujemy
# 10.255.2.1 10.255.3.19 10.255.3.86 10.255.3.111 10.255.3.123 10.255.3.222 - wtf? skanujemy
	echo 10.0.1.x
	(
	for ((i = 2; i <= 12; ++i)); do
                _get_hosta "10.0.1.$i"
        done
	) &
	 test $PARALLEL && kids="$kids $!" || wait $!
	for i in 1 2 3 4 5 6 7 8 11 12; do
		echo 10.$i.0.0
		(
		for ((j = 0; j <= 255; ++j)); do
			for ((k = 0; k <= 255; ++k)); do
				_get_hosta "10.$i.$j.$k"
			done
		done
		) &
		test $PARALLEL && kids="$kids $!" || wait $!
	done
	(
	for i in 10.255.2.1 10.255.3.19 10.255.3.86 10.255.3.111 10.255.3.123 10.255.3.222; do 
		_get_hosta "$i"
	done
	) &
	test $PARALLEL && kids="$kids $!" || wait $!
	
	echo waiting for pids $kids
	wait $kids
	
}

function ping_hosts()
{	
	local FILE_NEW=`mktemp`
	local kids=""
	local kids_num=0
	local kids_all=0
	
	test -f $FILE_NEW && rm $FILE_NEW
	
	echo dfasfdas 
	
	if $SCAN_CONDITION; then
		# we scan only hosts that are in our database
		hosts=$( $MYSQL_CMD "SELECT DISTINCT hostname FROM $QSEARCH_TABLE order by hostname;" )
		echo $hosts
	else
		# we ping all hosts in our database 
		hosts=$( $MYSQL_CMD "SELECT DISTINCT hostname FROM $HOSTS_TABLE order by hostname;" | tail -n +2 )
	fi
	
	$DEBUG && echo hosts: $hosts
	
	# ping hosts symultanuously
	for i in $hosts; do
		i=$i$DOMAIN_APPEND
		
		$debug && echo "all: $kids_all. this $kids_num -> nmap -p 21,139 $i >/dev/null 2>/dev/null && echo $i >> $FILE_NEW"
		( test ! -z "$(nmap -PN -p 21,139 $i 2>/dev/null | grep open)" && echo $i >> $FILE_NEW ) & 
		kids="$kids $!"
		kids_num=$[$kids_num+1]
		kids_all=$[$kids_all+1]
			
		while test $SCAN_MAX_KIDS_NUM -le $kids_num; do
			for PID in $kids; do
				if test ! -f /proc/$PID/exe; then
					kids=$( echo "$kids" | sed 's/'$PID'//' )
					kids_num=$[$kids_num-1]
				fi
			done
			sleep 1
		done
		
	done
	$debug && echo "wait $kids"
	wait $kids
	
	cp $FILE_NEW $PING_FILE_TO_WRITE_ACTIVE_HOSTS
	
	while read line; do
		$DEBUG && echo $MYSQL_CMD "update $HOSTS_TABLE set active=NOW() where hostname = $(echo $line | sed 's/'$DOMAIN_APPEND'//');"
		$MYSQL_CMD "update $HOSTS_TABLE set active=NOW() where hostname = '$(echo $line | sed 's/'$DOMAIN_APPEND'//')';"
	done < $FILE_NEW
}

function scan_hosts()
{
	local kids=""
	local kids_num=0
	local kids_all=0
	local again=true
	
	if test $SCAN_CONDITION; then
		# we scan only hosts that weren't scanned for $SCAN_MINUTES minutes
		cond=$( date +'%F %T' -d "$SCAN_MINUTES minutes ago" )
		list=$( $MYSQL_CMD "select ip, hostname from $HOSTS_TABLE where scanned <= '$cond' " )
	else
		# we scan all hosts in our database 
		list=$( $MYSQL_CMD "select ip, hostname from $HOSTS_TABLE ;" | tail -n +2)
	fi

	$DEBUG && echo $list
	
	for i in $list; do
		if $again; then
			ip=$i
			again=false
			continue
		else
			name=$i
			again=true
		fi
		
		if test ! -z "$(ps a | grep qsearch | awk '{print $6}'| tr '\n' ' ' | grep $name)"; then
			echo host $name with $ip is still scanning. dont running it again.
			continue;
		fi	
		( $QSEARCH_BINARY $name $ip >/dev/null ) &
		pid=$!
		kids="$kids $pid"
		kids_num=$[$kids_num+1]
		kids_all=$[$kids_all+1]
		$DEBUG && echo "all_kids $kids_all - num $kids_num -> PID $pid -> $QSEARCH_BINARY $name $ip"
		
		while test $SCAN_MAX_KIDS_NUM -le $kids_num; do
			for PID in $kids; do
				if test ! -f "/proc/$PID/exe"; then
					kids=$(echo "$kids" | sed 's/'$PID'//' )
					kids_num=$[$kids_num-1]
				fi
			done
			sleep 1
		done
	done
}

echo running as instance of $function_pnt
$function_pnt
